﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using ICSharpCode.SharpZipLib.Zip;
using ICSharpCode.SharpZipLib.Checksums;
using SetSailModel;
using System.Net.NetworkInformation;

namespace SetSailCommon
{
    public class CommonHelper
    {
        /// <summary>
        /// 获取GUID
        /// </summary>
        /// <returns></returns>
        public static string GetNewGuid()
        {
            return Guid.NewGuid().ToString().Replace("-", "").ToUpper().Trim();
        }

        /// <summary>
        /// 根据集合返回Combobox指定格式
        /// </summary>
        /// <param name="ls"></param>
        /// <returns></returns>
        public static List<KeyValuePair<string, string>> ComDataSource(List<Cookie_ZD> ls)
        {
            List<KeyValuePair<string, string>> lstCom = new List<KeyValuePair<string, string>>();
            foreach (var item in ls)
            {
                lstCom.Add(new KeyValuePair<string, string>(item.MXDM, item.MXMC));
            }
            return lstCom;
        }

        /// <summary>
        /// MD5加密
        /// </summary>
        /// <param name="strText"></param>
        /// <returns></returns>
        public static string MD5Encrypt(string strText)
        {
            try
            {
                byte[] result = Encoding.Default.GetBytes(strText);
                MD5 md5 = new MD5CryptoServiceProvider();
                byte[] output = md5.ComputeHash(result);
                return BitConverter.ToString(output).Replace("-", "").ToLower();
            }
            catch (Exception ex)
            {
                return ex.Message;
            }
        }

        /// <summary>
        /// 查看服务器是否能ping成功
        /// </summary>
        /// <returns></returns>
        public static bool GetPing()
        {
            bool online = false; //是否在线
            Ping ping = new Ping();
            PingReply pingReply = ping.Send("43.137.51.99");
            if (pingReply.Status == IPStatus.Success)
            {
                online = true;
            }
            else
            {
            }
            return online;
        }

        #region 获取版本号

        public string AssemblyFileVersion()
        {

            object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyFileVersionAttribute), false);
            if (attributes.Length == 0)
            {
                return "";
            }
            else
            {
                return ((AssemblyFileVersionAttribute)attributes[0]).Version;
            }

        }

        //得到指定程序集版本
        public string GetAssemblyVersion(string name)
        {
            byte[] filedata = File.ReadAllBytes(name + ".exe");
            return Assembly.Load(filedata).GetName().Version.ToString();

        }
        #endregion

        #region 文件和目录操作

        /// <summary>
        /// 删除文件夹以及文件
        /// </summary>
        /// <param name="directoryPath"> 文件夹路径 </param>
        /// <param name="fileName"> 文件名称 </param>
        public static void DeleteDirectoryOrFlie(string directoryPath, string fileName)
        {
            List<string> ls = new List<string>();
            //删除文件夹
            for (int i = 0; i < Directory.GetDirectories(directoryPath).ToList().Count; i++)
            {
                if (Directory.GetDirectories(directoryPath)[i].Contains(fileName))
                {
                    ls.Add(Directory.GetDirectories(directoryPath)[i]);
                }
            }

            foreach (var item in ls)
            {
                Directory.Delete(item, true);
            }
        }

        /// <summary>
        /// 删除文件夹
        /// </summary>
        /// <param name="directoryPath"> 文件夹路径 </param>
        /// <param name="fileName"> 文件名称 </param>
        public static string DeleteDirectory(string directoryPath, string fileName)
        {
            string err = "";
            try
            {
                Directory.Delete(directoryPath + "\\" + fileName, true);
            }
            catch (Exception ex)
            {
                err = ex.Message;
            }
            return err;
        }

        /// <summary>
        /// 读取txt文件内容
        /// </summary>
        /// <param name="Path">文件地址</param>
        public static void ReadTxtContent(string Path)
        {
            StreamReader sr = new StreamReader(Path, Encoding.Default);
            string content;
            while ((content = sr.ReadLine()) != null)
            {
                Console.WriteLine(content.ToString());
            }
        }

        /// <summary>
        /// 加密、解密
        /// </summary>
        private static byte[] key = new byte[] { 78, 56, 61, 94, 12, 88, 56, 63, 66, 111, 102, 77, 1, 186, 97, 45 };
        private static byte[] iv = new byte[] { 36, 34, 42, 122, 242, 87, 2, 90, 59, 117, 123, 63, 72, 171, 130, 61 };

        private static IFormatter S_Formatter = new BinaryFormatter();//创建一个序列化的对象
        /// <summary>
        /// 采用Rijndael128位加密二进制可序列化对象至文件
        /// </summary>
        /// <param name="para">二进制对象</param>
        /// <param name="filePath">文件路径</param>
        /// <returns></returns>
        public static bool EncryptObject(object para, string filePath)
        {
            //创建.bat文件 如果之前错在.bat文件则覆盖，无则创建
            using (Stream fs = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None))
            {
                RijndaelManaged RMCrypto = new RijndaelManaged();
                CryptoStream csEncrypt = new CryptoStream(fs, RMCrypto.CreateEncryptor(key, iv), CryptoStreamMode.Write);
                S_Formatter.Serialize(csEncrypt, para);//将数据序列化后给csEncrypt
                csEncrypt.Close();
                fs.Close();
                return true;
            }
        }

        /// <summary>
        /// 从采用Rijndael128位加密的文件读取二进制对象
        /// </summary>
        /// <param name="filePath">文件路径</param>
        /// <returns>二进制对象</returns>
        public static object DecryptObject(string filePath)
        {
            //打开.bat文件
            using (Stream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read))
            {
                object para;
                RijndaelManaged RMCrypto = new RijndaelManaged();
                CryptoStream csEncrypt = new CryptoStream(fs, RMCrypto.CreateDecryptor(key, iv), CryptoStreamMode.Read);
                para = S_Formatter.Deserialize(csEncrypt); //将csEncrypt反序列化回原来的数据格式；
                csEncrypt.Close();
                fs.Close();
                return para;
            }
        }

        #endregion

        #region 压缩
        /// <summary>
        /// 压缩文件
        /// </summary>
        /// <param name="sourceFilePath"></param>
        /// <param name="destinationZipFilePath"></param>
        public static void CreateZip(string sourceFilePath, string destinationZipFilePath, string pathfile)
        {
            if (sourceFilePath[sourceFilePath.Length - 1] != System.IO.Path.DirectorySeparatorChar)
                sourceFilePath += System.IO.Path.DirectorySeparatorChar;

            ZipOutputStream zipStream = new ZipOutputStream(File.Create(destinationZipFilePath));
            zipStream.SetLevel(6);  // 压缩级别 0-9
            CreateZipFiles(sourceFilePath, zipStream, sourceFilePath, pathfile);

            zipStream.Finish();
            zipStream.Close();
        }

        /// <summary>
        /// 递归压缩文件
        /// </summary>
        /// <param name="sourceFilePath">待压缩的文件或文件夹路径</param>
        /// <param name="zipStream">打包结果的zip文件路径（类似 D:\WorkSpace\a.zip）,全路径包括文件名和.zip扩展名</param>
        /// <param name="staticFile"></param>
        private static void CreateZipFiles(string sourceFilePath, ZipOutputStream zipStream, string staticFile, string pathfile)
        {
            Crc32 crc = new Crc32();
            string[] filesArray = Directory.GetFileSystemEntries(sourceFilePath);
            foreach (string file in filesArray)
            {
                if (!file.Contains(pathfile) || file.Contains(".zip"))
                    continue;
                if (Directory.Exists(file))                     //如果当前是文件夹，递归
                {
                    CreateZipFiles(file, zipStream, staticFile, pathfile);
                }
                else                                            //如果是文件，开始压缩
                {
                    FileStream fileStream = File.OpenRead(file);

                    byte[] buffer = new byte[fileStream.Length];
                    fileStream.Read(buffer, 0, buffer.Length);
                    string tempFile = file.Substring(staticFile.LastIndexOf("\\") + 1);
                    if (tempFile.Contains("config.cfg") || tempFile.Contains("config_local.cfg") || tempFile.Contains("controls.sii"))
                        continue;
                    ZipEntry entry = new ZipEntry(tempFile);

                    entry.DateTime = DateTime.Now;
                    entry.Size = fileStream.Length;
                    fileStream.Close();
                    crc.Reset();
                    crc.Update(buffer);
                    entry.Crc = crc.Value;
                    zipStream.PutNextEntry(entry);

                    zipStream.Write(buffer, 0, buffer.Length);
                }
            }
        }

        #endregion

        #region 解压缩
        /// <summary>   
        /// 功能：解压zip格式的文件。   
        /// </summary>   
        /// <param name="zipFilePath">压缩文件路径</param>   
        /// <param name="unZipDir">解压文件存放路径,为空时默认与压缩文件同一级目录下，跟压缩文件同名的文件夹</param>   
        /// <param name="err">出错信息</param>   
        /// <returns>解压是否成功</returns>   
        public static bool UnZipFile(string zipFilePath, string unZipDir, out string err)
        {
            err = "";
            if (zipFilePath == string.Empty)
            {
                err = "压缩文件不能为空！";
                return false;
            }
            if (!File.Exists(zipFilePath))
            {
                err = "压缩文件不存在！";
                return false;
            }
            //解压文件夹为空时默认与压缩文件同一级目录下，跟压缩文件同名的文件夹   
            if (unZipDir == string.Empty)
                unZipDir = zipFilePath.Replace(Path.GetFileName(zipFilePath), Path.GetFileNameWithoutExtension(zipFilePath));
            if (!unZipDir.EndsWith("\\"))
                unZipDir += "\\";
            if (!Directory.Exists(unZipDir))
                Directory.CreateDirectory(unZipDir);

            try
            {
                using (ZipInputStream s = new ZipInputStream(File.OpenRead(zipFilePath)))
                {

                    ZipEntry theEntry;
                    while ((theEntry = s.GetNextEntry()) != null)
                    {
                        string directoryName = Path.GetDirectoryName(theEntry.Name);
                        string fileName = Path.GetFileName(theEntry.Name);
                        if (fileName.Contains("config.cfg") || fileName.Contains("config_local.cfg") || fileName.Contains("controls.sii"))
                            continue;
                        if (directoryName.Length > 0)
                        {
                            Directory.CreateDirectory(unZipDir + directoryName);
                        }
                        if (!directoryName.EndsWith("\\"))
                            directoryName += "\\";
                        if (fileName != String.Empty)
                        {
                            using (FileStream streamWriter = File.Create(unZipDir + theEntry.Name))
                            {

                                int size = 2048;
                                byte[] data = new byte[2048];
                                while (true)
                                {
                                    size = s.Read(data, 0, data.Length);
                                    if (size > 0)
                                    {
                                        streamWriter.Write(data, 0, size);
                                    }
                                    else
                                    {
                                        break;
                                    }
                                }
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                err = ex.Message;
                return false;
            }
            return true;
        }

        #endregion
    }
}
